<?php
/**
 * Created by PhpStorm.
 * User: zyark
 * Date: 2018/4/1
 * Time: 17:30
 */

namespace app\index\logic;


use app\admin\logic\MoneyLogic;
use app\common\model\Page;
use app\common\utils\Constant;
use think\Collection;
use think\Controller;
use think\Db;
use think\Exception;
use think\Loader;
use think\Log;
use WxPayApi;
use WxPayRefund;

class RedEnvelopeLogic
{
    /**
     * ajax获取红包列表
     * @param $data
     * @param $get_user_info=false
     * @return mixed
     */
    public function getRedEnvelopeList($data,$get_user_info=false){
        $map = [];
        if(!isset($data['page_size'])){
            $data['page_size'] = 10;
        }
        if(!isset($data['page_num'])){
            $data['page_num'] = 1;
        }
        if(isset($data['user_id']) && !empty($data['user_id'])){
            $map['user_id'] = $data['user_id'];
        }
        if(isset($data['status'])){
            $map['status'] = $data['status'];
        }
        if(isset($data['status_arr']) && is_array($data['status_arr']) && count($data['status_arr']) > 0){
            $map['status'] = array('in',$data['status_arr']);
        }
        if(isset($data['is_visible'])){
            $map['is_visible'] = $data['is_visible'];
        }

        $result = $this->queryByMap($map,$data['page_num'],$data['page_size']);
        if($get_user_info) {
            foreach ($result['list'] as $key => &$value) {
                $user = model('User')->where(array('id' => $value['user_id']))->field('avatar,nickname')->find();
                $value['avatar'] = $user['avatar'];
                $value['nickname'] = $user['nickname'];
            }
            unset($value);
        }
        return $result;
    }

    /**
     * 随机获取n条附近红包
     * @return false|\PDOStatement|string|Collection
     */
    public function getNearReadEnvelopeList(){
//        $status_arr = [Constant::RED_ENVELOPE_STATUS_NO_CHALLENGE,Constant::RED_ENVELOPE_STATUS_IN_THE_CHALLENGE];
//        $map['status'] = ['in',$status_arr];
        $map['is_visible'] = 1;
        $number = model('Config')->where(array('name'=>Constant::CONFIG_NAME_SHOW_RED_NUMBER))->value('value');
        $list = $this->get_random_data($number,$map);
        foreach ($list as $key => &$value) {
            $user = model('User')->where(array('id' => $value['user_id']))->field('avatar,nickname')->find();
            $value['avatar'] = $user['avatar'];
            $value['nickname'] = $user['nickname'];
        }
        unset($value);
        return $list;
    }

    /**
     * 随机获取n条数据
     * @param $num
     * @param $map
     * @return false|\PDOStatement|string|Collection
     */
    private function get_random_data($num,$map)
    {
        $model = model('RedEnvelope');
        $pk = $model->getPK();//获取主键
        $map['is_pay'] = 1;
        $countcus = $model->where($map)->field($pk)->select();//查询数据;
        if(count($countcus) < $num){
            $list = $model->where($map)
                ->field('topic_ids,topic_grade',true)
                ->select();
            return $list;
        }
        $query = [];
        $ids = [];
        foreach($countcus as $v=>$val){
            $ids[]=$val[$pk];
        }
        shuffle($ids);
        for($i = 0;$i < $num;$i++){
            $query[] = $ids[$i];
        }
        $list = $model->where($pk,'in',$query)
            ->field('topic_ids,topic_grade',true)
            ->select();
        return $list;
    }

    /**
     * 根据红包id获取红包详情
     * @param $red_envelope_id int 红包id
     * @return mixed
     */
    public function getRedEnvelopeById($red_envelope_id){
        $data = model('RedEnvelope')
            ->where(array('id'=>$red_envelope_id))
            ->field('topic_ids,topic_grade',true)
            ->find();
        if(!$data || $data['is_pay'] != 1){
            return array('status'=>2,'msg'=>'该挑战记录不存在！');
        }
        $user = model('User')->where(array('id' => $data['user_id']))->field('avatar,nickname')->find();
        $data['avatar'] = $user['avatar'];
        $data['nickname'] = $user['nickname'];
        return array('status'=>1,'data'=>$data);
    }

    private function queryByMap($map,$page_num,$page_size){
        $startno = ($page_num - 1) * $page_size;
        $map['is_pay'] = 1;
        $list = model('RedEnvelope')
            ->where($map)
            ->limit($startno,$page_size)
            ->order('id','desc')
            ->field('topic_ids,topic_grade',true)
            ->select();
        $count = model('RedEnvelope')
            ->where($map)
            ->count();
        $result['list'] = $list;
        $page = new Page($page_num,$count,$page_size);
        $result['page'] = $page;
        return $result;
    }

    /**
     * 创建红包并创建订单
     * @param $standard_id int 红包规则id
     * @param $is_visible int 是否附近可见
     * @param $user_id int 用户id
     * @return array
     */
    public function createRedEnvelopeAndOrder($standard_id,$is_visible,$user_id){
        Db::startTrans();
        try{
            $standard = model('Standard')->where(array('id'=>$standard_id))->find();
            if(!$standard){
                return array('status'=>2,'msg'=>'请勿非法提交');
            }
            $red_envelope_id = $this->createRedEnvelope($standard,$is_visible,$user_id);
            $order = $this->createOrderByRedEnvelope($user_id,$red_envelope_id,$standard['money']);
            $data['money'] = $order['money'];
            $data['number'] = $order['number'];
            $data['red_envelope_id'] = $red_envelope_id;
            $data['open_id'] = model('User')->where(array('id'=>$user_id))->value('open_id');
            Db::commit();
            return array('status'=>1,'data'=>$data);
        }catch (Exception $e){
            Db::rollback();
            return array('status'=>0,'error'=>$e->getMessage());
        }
    }

    /**
     * 生成红包订单
     * @param $user_id
     * @param $red_envelope_id
     * @param $money
     * @return mixed
     */
    private function createOrderByRedEnvelope($user_id,$red_envelope_id,$money){
        $order = $this->makeOrder(Constant::ORDER_TYPE_SEND_RED_ENVELOPE,$red_envelope_id,$money);
        $order['user_id'] = $user_id;
        $order['pay_type'] = Constant::ORDER_PAY_TYPE_WE_CHAT;
        $order_obj = model('Order')->create($order);
        return $order_obj;
    }

    /**
     * 构造订单
     * @param $order_type
     * @param $red_envelope_id
     * @param $money
     * @return mixed
     */
    private function makeOrder($order_type,$red_envelope_id,$money){
        $order['number'] = build_order_no();
        $order['is_pay'] = 0;
        $order['type'] = $order_type;
        $order['money'] = $money;
        $order['red_envelope_id'] = $red_envelope_id;
        $order['create_time'] = time();
        return $order;
    }

    /**
     * 创建红包
     * @param $standard
     * @param $is_visible
     * @param $user_id
     * @return mixed
     */
    private function createRedEnvelope($standard,$is_visible,$user_id){
        $data['money'] = $standard['money'];
        $data['answer_money'] = $standard['answer_money'];
        $data['topic_number'] = $standard['topic_number'];
        $data['topic_grade'] = $standard['topic_grade'];
        $data['user_id'] = $user_id;
        $data['is_pay'] = 0;
        $data['status'] = Constant::RED_ENVELOPE_STATUS_NO_CHALLENGE;//未挑战
        $data['is_visible'] = $is_visible;
        $data['create_time'] = time();
        $red_envelope = model('RedEnvelope')->create($data);
        return $red_envelope['id'];
    }

    /**
     * 撤回红包
     * @param $red_envelope_id int 红包id
     * @param $user_id int 用户id
     * @return mixed
     */
    public function withdraw($red_envelope_id,$user_id){
        Db::startTrans();
        try {
            $result = $this->checkWithdraw($red_envelope_id, $user_id);
            if ($result['status'] != 1) {
                return $result;
            }
            $money = model('RedEnvelope')
                ->where(array('id'=>$red_envelope_id))->value('money');
            model('User')
                ->where(array('id'=>$user_id))
                ->setInc('balance',$money);
            $this->saveWithdrawRedLog($money,$user_id);
            //撤回成功
            model('RedEnvelope')
                ->where(array('id'=>$red_envelope_id))
                ->setField('status',Constant::RED_ENVELOPE_STATUS_TO_WITHDRAW);
            Db::commit();
            return array('status' => 1);
        }catch (Exception $e){
            Db::rollback();
            return array('status' => 0, 'error' => $e->getMessage());
        }
    }

    /**
     * 存储红包撤回到余额资金记录
     * @param $money
     * @param $user_id
     */
    private function saveWithdrawRedLog($money,$user_id){
        $current_money = model('User')
            ->where(array('id'=>$user_id))
            ->value('balance');
        $logic = new MoneyLogic();
        $change_type = Constant::CHANGE_TYPE_WITHDRAW_RED;
        $in_out_type = Constant::IN_OUT_TYPE_IN;
        $money_type = Constant::MONEY_TYPE_BALANCE;
        $desc = '红包撤回';
        $logic->saveMoneyLog($money,$current_money,$change_type,
            $in_out_type,$desc,$user_id,$money_type,0);
    }

    /**
     * 判断是否可以撤回
     * @param $red_envelope_id
     * @param $user_id
     * @return array
     */
    private function checkWithdraw($red_envelope_id,$user_id){
        $red_envelope = model('RedEnvelope')->where(array('id'=>$red_envelope_id))->find();
        if(!$red_envelope || $red_envelope['is_pay'] == 0){
            return array('status'=>2,'msg'=>'该挑战记录不存在！');
        }
        if($red_envelope['user_id'] != $user_id){
            return array('status'=>2,'msg'=>'只有发起挑战的用户才能撤回！');
        }
        if($red_envelope['status'] != Constant::RED_ENVELOPE_STATUS_NO_CHALLENGE){
            return array('status'=>2,'msg'=>'该挑战无法被撤回！');
        }
        $withdraw_time = model('Config')->where(array('name'=>Constant::CONFIG_NAME_WITHDRAW_TIME))->value('value');
        $now = time();
        $timediff = $now - $red_envelope['create_time'];
        $days = intval($timediff/86400);
        $remain = $timediff % 86400;
        $hours = intval($remain / 3600);
        if($days>0) {
            $hours += $days * 24;
        }
        if($hours < $withdraw_time){
            return array('status'=>2,'msg'=>'该挑战无法被撤回！');
        }
        return array('status'=>1);
    }

    /**
     * 调用微信支付退款接口
     * @param $orderSn string 订单唯一标识
     * @param $refundMoney float 退款金额
     * @return mixed
     */
    public function refundByWeChat($orderSn, $refundMoney){
        Loader::import('wxpay.WxPayJsApiPay');
        Loader::import('wxpay.WxPayUnifiedOrder');
        Loader::import('wxpay.WxPayNotify');
//        return  array('msg'=>   \WxPayConfig::SSLKEY_PATH);
        $input = new \WxPayRefund();
//        out_refund_no、total_fee、refund_fee、op_user_id
        $input->SetOut_trade_no($orderSn);
        $input->SetOut_refund_no($orderSn);
        $input->SetTotal_fee($refundMoney*100);
        $input->SetRefund_fee($refundMoney*100);
        $input->SetOp_user_id(\WxPayConfig::MCHID);
        $result = \WxPayApi::refund($input);
        Log::write($result);
        if($result['return_code'] == 'SUCCESS')
            return array('status'=>1);
        return array('status'=>0,'data'=>$result);
    }
}